package com.trade.dao.impl;

import com.trade.dao.*;
import com.trade.dao.listener.*;
import com.trade.data.*;
import com.trade.data.type.*;
import java.util.*;
import java.util.zip.*;
import java.text.*;

import net.esper.client.Configuration;
import net.esper.client.EPAdministrator;
import net.esper.client.EPRuntime;
import net.esper.client.EPServiceProvider;
import net.esper.client.EPServiceProviderManager;
import net.esper.client.EPStatement;

import org.hibernate.*;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Scanner;
import java.util.Set;
import java.io.*;

import org.apache.http.HttpException;
import org.apache.http.HttpHost;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.params.ConnRoutePNames;
import org.apache.http.cookie.Cookie;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.impl.cookie.BasicClientCookie;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;

import org.supercsv.cellprocessor.*;
import org.supercsv.io.*;
import org.supercsv.cellprocessor.ift.*;
import org.supercsv.cellprocessor.constraint.*;
import org.supercsv.prefs.*;

import org.json.*;

public class EsperLivePriceDAO extends BaseDAO implements ILivePriceDAO {

	private Session session = null;
	private Configuration cepConfig = null;
	private EPRuntime cepRuntime = null;
	private EPAdministrator cepAdministrator = null;


	public EsperLivePriceDAO() {
		this.cepConfig = new Configuration();
		cepConfig.addEventTypeAlias("StockTick", EquityIntradayDataVO.class
				.getName());
		cepConfig.addEventTypeAlias("IndexTick", IndexIntradayDataVO.class
				.getName());

		cepConfig.addEventTypeAlias("StockGainTick", GainEventVO.class.getName());
		cepConfig.addEventTypeAlias("StockLossTick", LossEventVO.class.getName());

		EPServiceProvider cep = EPServiceProviderManager.getProvider(
				"myCEPEngine", cepConfig);
		this.cepRuntime = cep.getEPRuntime();
		this.cepAdministrator = cep.getEPAdministrator();

		EPStatement stockStatement = getStockCEPStatement();
		stockStatement.addListener(new PriceUpdateListener());

		EPStatement stockAvg5Statement = getStockAvg5CEPStatement();
		stockAvg5Statement.addListener(new PriceAvgUpdateListener());

		EPStatement stockAvg9Statement = getStockAvg9CEPStatement();
		stockAvg9Statement.addListener(new PriceAvgUpdateListener());

		EPStatement stockAvg12Statement = getStockAvg12CEPStatement();
		stockAvg12Statement.addListener(new PriceAvgUpdateListener());

		EPStatement stockAvg20Statement = getStockAvg20CEPStatement();
		stockAvg20Statement.addListener(new PriceAvgUpdateListener());

		EPStatement stockAvg26Statement = getStockAvg26CEPStatement();
		stockAvg26Statement.addListener(new PriceAvgUpdateListener());

		EPStatement stockAvg50Statement = getStockAvg50CEPStatement();
		stockAvg50Statement.addListener(new PriceAvgUpdateListener());

		EPStatement stockAvg100Statement = getStockAvg100CEPStatement();
		stockAvg100Statement.addListener(new PriceAvgUpdateListener());

		EPStatement stockAvg200Statement = getStockAvg200CEPStatement();
		stockAvg200Statement.addListener(new PriceAvgUpdateListener());

		//RSI
		EPStatement stockGainStatement = getStockGainCEPStatement();
		stockGainStatement.addListener(new PriceGainOrLossUpdateListener());

		EPStatement stockLossStatement = getStockLossCEPStatement();
		stockLossStatement.addListener(new PriceGainOrLossUpdateListener());

		// EPStatement indexStatement = getIndexCEPStatement();
		// indexStatement.addListener(new PriceUpdateListener());


	}

	public Configuration getCepConfig() {
		return cepConfig;
	}

	public EPRuntime getCepRuntime() {
		return cepRuntime;
	}

	public EPAdministrator getCepAdministrator() {
		return cepAdministrator;
	}

	public void sendEvent(Object object)throws Exception{
		this.cepRuntime.sendEvent(object);
	}

	private EPStatement getIndexCEPStatement() {
		return cepAdministrator.createEQL("select * from "
				+ " IndexTick.win:length(10)");
	}

	private EPStatement getStockCEPStatement() {
		return cepAdministrator.createEQL("select * from StockTick.win:length(1)");
	}


	/**
	 * Calcualte 5SMA for calculate
	 *
	 * @return
	 */
	private EPStatement getStockAvg5CEPStatement() {
		return cepAdministrator
				.createEQL("select symbol,1 as calType, 5 as calDays, avg(close) as calValue from StockTick.win:length(5) group by symbol,calType,calDays");
	}


	/**
	 * Calcualte 9SMA for calculate 12EMA for MACD
	 *
	 * @return
	 */
	private EPStatement getStockAvg9CEPStatement() {
		return cepAdministrator
				.createEQL("select symbol,1 as calType, 9 as calDays, avg(close) as calValue from StockTick.win:length(9) group by symbol,calType,calDays");
	}


	/**
	 * Calcualte 12SMA for calculate 12EMA for MACD
	 *
	 * @return
	 */
	private EPStatement getStockAvg12CEPStatement() {
		return cepAdministrator
				.createEQL("select symbol,1 as calType, 12 as calDays, avg(close) as calValue from StockTick.win:length(12) group by symbol,calType,calDays");
	}

	/**
	 * Calculate 20SMA
	 *
	 * @return
	 */
	private EPStatement getStockAvg20CEPStatement() {
		return cepAdministrator
				.createEQL("select symbol,1 as calType, 20 as calDays, avg(close) as calValue from StockTick.win:length(20) group by symbol,calType,calDays");
	}

	/**
	 * Calculate 20SMA
	 *
	 * @return
	 */
	private EPStatement getStockAvg26CEPStatement() {
		return cepAdministrator
				.createEQL("select symbol,1 as calType, 26 as calDays, avg(close) as calValue from StockTick.win:length(26) group by symbol,calType,calDays");
	}


	/**
	 * Calculate 50SMA
	 *
	 * @return
	 */
	private EPStatement getStockAvg50CEPStatement() {
		return cepAdministrator
				.createEQL("select symbol,1 as calType, 50 as calDays, avg(close) as calValue from StockTick.win:length(50) group by symbol,calType,calDays");
	}

	/**
	 * Calculate 100SMA
	 *
	 * @return
	 */
	private EPStatement getStockAvg100CEPStatement() {
		return cepAdministrator
				.createEQL("select symbol,1 as calType, 100 as calDays, avg(close) as calValue from StockTick.win:length(100) group by symbol,calType,calDays");
	}

	/**
	 * Calculate 200SMA
	 *
	 * @return
	 */
	private EPStatement getStockAvg200CEPStatement() {
		return cepAdministrator
				.createEQL("select symbol,1 as calType, 200 as calDays, avg(close) as calValue from StockTick.win:length(200) group by symbol,calType,calDays");
	}

	/**
	 * Calculate Average of Gain
	 * @return
	 */

	private EPStatement getStockGainCEPStatement() {
		return cepAdministrator
				.createEQL("select symbol,close,avg(value)  from StockGainTick.win:length(14) group by symbol");
	}

	/**
	 * Calculate Average of loss
	 * @return
	 */
	private EPStatement getStockLossCEPStatement() {
		return cepAdministrator
				.createEQL("select symbol,close,avg(value) as value from StockLossTick.win:length(14) group by symbol");
	}



	/**
	 * This method return Index and Stock historical data.
	 *
	 */
	public synchronized List<HistoricalDataVO> getPrice(HistoricalDataFilterVO filterVO)
			throws Exception {
		List<HistoricalDataVO> instrumentHistList = new ArrayList<HistoricalDataVO>();

		DateFormat formatter = new SimpleDateFormat("hh:mma z");
		NumberFormat numberFormatter = NumberFormat.getInstance();

		try {
			HttpHost proxy = new HttpHost("test", 8443);
			DefaultHttpClient httpclient = new DefaultHttpClient();
			//httpclient.getParams().setParameter(ConnRoutePNames.DEFAULT_PROXY,			proxy);
			// http://finance.google.com/finance/info?client=ig&q=NIFTY:SBIN,NIFTY:BHEL
			// http://www.google.com/finance/getprices?q=SBIN&x=NSE&i=120&p=10m&f=d,c,v,o,h,l&df=cpct&auto=1&ts=1352181525283&ei=fqSYUIDBFKrE0QGyBg

			String url = "http://finance.google.com/finance/info?client=ig&q=";

			StringBuffer sb = new StringBuffer();

			for (String ticker : filterVO.getTickerList()) {
				sb.append("NSE:" + ticker + ",");
			}

			url = url + sb.toString();

			System.out.println(url);

			HttpGet httpget = new HttpGet(url);

			httpget.getParams().setParameter("http.socket.timeout",
					new Integer(30000));

			httpget.setHeader("Host", "finance.google.com");
			httpget
					.setHeader(
							"User-Agent",
							"Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.2.12) Gecko/20101026 Firefox/3.6.12");
			httpget
					.setHeader("Accept",
							"text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8");
			httpget.setHeader("Accept-Charset",
					"ISO-8859-1,utf-8;q=0.7,*;q=0.7");
			httpget.setHeader("Accept-Encoding", "gzip,deflate");
			httpget.setHeader("Accept-Language", "en-us,en;q=0.5");
			httpget.setHeader("Connection", "keep-alive");
			httpget.setHeader("Keep-Alive", "115");
			httpget.setHeader("Content-Type",
					"application/x-www-form-urlencoded; charset=UTF-8");

			HttpResponse response = httpclient.execute(httpget);

			GZIPInputStream zipIn = new GZIPInputStream(response.getEntity()
					.getContent());

			StringBuffer responseString = new StringBuffer();
			Scanner sc = new Scanner(zipIn);
			int j = 0;
			while (sc.hasNextLine()) {
				String data = sc.nextLine();
				if (j == 0) {
					data = data.replaceAll("//", "");
				}
				responseString.append(data);
			}

			System.out.println(responseString.toString());

			JSONArray jsonArray = new JSONArray(responseString.toString());

			for (int i = 0; i < jsonArray.length(); i++) {
				JSONObject jsonObject = jsonArray.getJSONObject(i);
				HistoricalDataVO histDataVO = null;

				if ("NIFTY".equals(jsonObject.getString("t"))) {
					histDataVO = new IndexIntradayDataVO();
				} else {
					histDataVO = new EquityIntradayDataVO();
				}

				histDataVO.setSymbol(jsonObject.getString("t"));
				histDataVO
						.setDate(formatter.parse(jsonObject.getString("ltt")));
				histDataVO.setClose(numberFormatter.parse(
						jsonObject.getString("l")).doubleValue());

				this.cepRuntime.sendEvent(histDataVO);

				instrumentHistList.add(histDataVO);

				// System.out.println(jsonObject.getString("t")+" , "+jsonObject.getString("ltt")+" , "+jsonObject.getString("l"));
			}

			// System.out.println("Price List - "+instrumentHistList);

		} catch (Exception e) {
			System.out.println("Equity - " + e);
			throw new Exception(e);
		} finally {
		}

		return instrumentHistList;
	}

	/**
	 * This method return Index and Stock historical data.
	 *
	 */
	public synchronized List<HistoricalDataVO> getClosePrices(HistoricalDataFilterVO filterVO)
			throws Exception {
		List<HistoricalDataVO> instrumentHistList = new ArrayList<HistoricalDataVO>();

		DateFormat formatter = new SimpleDateFormat("hh:mma z");
		NumberFormat numberFormatter = NumberFormat.getInstance();

		try {
			//HttpHost proxy = new HttpHost("test", 8443);
			DefaultHttpClient httpclient = new DefaultHttpClient();
			//httpclient.getParams().setParameter(ConnRoutePNames.DEFAULT_PROXY,proxy);
			// COLUMNS=DATE,CLOSE,HIGH,LOW,OPEN,VOLUME
			// http://www.google.com/finance/getprices?q=SBIN&x=NSE&i=120&p=10m&f=d,c,v,o,h,l&df=cpct&auto=1&ts=1352181525283&ei=fqSYUIDBFKrE0QGyBg

			for (String symbol : filterVO.getTickerList()) {

				String url = "http://www.google.com/finance/getprices?q="+ symbol +"&i="
						+ filterVO.getInterval().getPeriodValue() + "&p=" + filterVO.getNoOfPeriod()
						+ "d&f=d,o,h,l,c,v";

				HttpGet httpget = new HttpGet(url);

				httpget.getParams().setParameter("http.socket.timeout",
						new Integer(30000));

				httpget.setHeader("Host", "www.google.com");
				httpget
						.setHeader(
								"User-Agent",
								"Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.2.12) Gecko/20101026 Firefox/3.6.12");
				httpget
						.setHeader("Accept",
								"text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8");
				httpget.setHeader("Accept-Charset",
						"ISO-8859-1,utf-8;q=0.7,*;q=0.7");
				httpget.setHeader("Accept-Encoding", "gzip,deflate");
				httpget.setHeader("Accept-Language", "en-us,en;q=0.5");
				httpget.setHeader("Connection", "keep-alive");
				httpget.setHeader("Keep-Alive", "115");
				// httpget.setHeader("Content-Type",
				// "application/x-www-form-urlencoded; charset=UTF-8");

				HttpResponse response = httpclient.execute(httpget);

				GZIPInputStream zipIn = new GZIPInputStream(response.getEntity()
						.getContent());

				StringBuffer responseString = new StringBuffer();
				Scanner sc = new Scanner(zipIn);
				int j = 0;
				String data = null;
				while (sc.hasNextLine()) {
					data = sc.nextLine();
					responseString.append(data + "\n");

					if (j++ > 7) {
						String arr[] = data.split(",");

						HistoricalDataVO histDataVO = new EquityIntradayDataVO();

						// COLUMNS=DATE,CLOSE,HIGH,LOW,OPEN,VOLUME
						histDataVO.setSymbol("SBIN");
						histDataVO.setDate(new Date());
						histDataVO.setClose(Double.valueOf(arr[1]));
						histDataVO.setHigh(Double.valueOf(arr[2]));
						histDataVO.setLow(Double.valueOf(arr[3]));
						histDataVO.setOpen(Double.valueOf(arr[4]));
						histDataVO.setVolume(Double.valueOf(arr[5]));

						this.cepRuntime.sendEvent(histDataVO);

						System.out.println("SBIN Data close - "
								+ histDataVO.getClose() + ", high - "
								+ histDataVO.getHigh());
					}

					Thread.sleep(100);
				}

			}

		} catch (Exception e) {
			System.out.println("Equity - " + e.toString());
			throw new Exception(e);
		} finally {
		}

		return instrumentHistList;
	}

	/**
	 * This method return Stock and Index Intraday prices
	 *
	 */
	public synchronized List<HistoricalDataVO> getIntradayClosePrices(
			HistoricalDataFilterVO filterVO) throws Exception {
		List<HistoricalDataVO> instrumentHistList = new ArrayList<HistoricalDataVO>();

		DateFormat formatter = new SimpleDateFormat("hh:mma z");
		NumberFormat numberFormatter = NumberFormat.getInstance();

		try {
			//HttpHost proxy = new HttpHost("test", 8443);
			DefaultHttpClient httpclient = new DefaultHttpClient();
			//httpclient.getParams().setParameter(ConnRoutePNames.DEFAULT_PROXY,proxy);
			// COLUMNS=DATE,CLOSE,HIGH,LOW,OPEN,VOLUME
			// http://www.google.com/finance/getprices?q=SBIN&x=NSE&i=120&p=10m&f=d,c,v,o,h,l&df=cpct&auto=1&ts=1352181525283&ei=fqSYUIDBFKrE0QGyBg
			for (String symbol : filterVO.getTickerList()) {

				String url = "http://www.google.com/finance/getprices?q="+ symbol +"&i="
						+ filterVO.getInterval().getPeriodValue()
						+ "&p="
						+ filterVO.getNoOfPeriod() + "d&f=d,o,h,l,c,v";

				HttpGet httpget = new HttpGet(url);

				httpget.getParams().setParameter("http.socket.timeout",
						new Integer(30000));

				httpget.setHeader("Host", "www.google.com");
				httpget
						.setHeader(
								"User-Agent",
								"Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.2.12) Gecko/20101026 Firefox/3.6.12");
				httpget
						.setHeader("Accept",
								"text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8");
				httpget.setHeader("Accept-Charset",
						"ISO-8859-1,utf-8;q=0.7,*;q=0.7");
				httpget.setHeader("Accept-Encoding", "gzip,deflate");
				httpget.setHeader("Accept-Language", "en-us,en;q=0.5");
				httpget.setHeader("Connection", "keep-alive");
				httpget.setHeader("Keep-Alive", "115");
				// httpget.setHeader("Content-Type",
				// "application/x-www-form-urlencoded; charset=UTF-8");

				HttpResponse response = httpclient.execute(httpget);

				GZIPInputStream zipIn = new GZIPInputStream(response
						.getEntity().getContent());

				StringBuffer responseString = new StringBuffer();
				Scanner sc = new Scanner(zipIn);
				String data = null;
				while (sc.hasNextLine()) {
					data = sc.nextLine();
					responseString.append(data + "\n");
				}

				String arr[] = data.split(",");

				HistoricalDataVO histDataVO = new EquityIntradayDataVO();

				// COLUMNS=DATE,CLOSE,HIGH,LOW,OPEN,VOLUME
				histDataVO.setSymbol(symbol);
				histDataVO.setDate(new Date());
				histDataVO.setClose(Double.valueOf(arr[1]));
				histDataVO.setHigh(Double.valueOf(arr[2]));
				histDataVO.setLow(Double.valueOf(arr[3]));
				histDataVO.setOpen(Double.valueOf(arr[4]));
				histDataVO.setVolume(Double.valueOf(arr[5]));

				this.cepRuntime.sendEvent(histDataVO);


				System.out.println("SBIN Data close - " + histDataVO.getClose()
						+ ", high - " + histDataVO.getHigh());

			}
		} catch (Exception e) {
			System.out.println("Equity - " + e.toString());
			throw new Exception(e);
		} finally {
		}

		return instrumentHistList;
	}

	private synchronized List<NameValuePair> getParam(Map<String, String> map) {
		List<NameValuePair> param = new ArrayList<NameValuePair>();
		Set<String> set = map.keySet();
		for (String s : set) {
			param.add(new BasicNameValuePair(s, map.get(s) != null ? map.get(s)
					: ""));
		}
		return param;
	}

}